/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * All Rights Researved.
 *
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 *
 * @author: jin Chen
 * @date: Jun 20, 2003
 * @version: $VERSION$
 */
package edu.psu.geovista.app.plot.axis;

import edu.psu.geovista.app.plot.ruler.ColorRuler;
import edu.psu.geovista.app.plot.ruler.Ruler;
import edu.psu.geovista.classification.CategoryList;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import java.awt.*;

public class BasicAxisUI extends ComponentUI{
    protected BasicAxis axis;
    //protected Ruler ruler;
    protected ChangeHandler axisStateMonitor;

    public BasicAxisUI(BasicAxis axis) {
        this.axis = axis;
    }

    /////////////////////////////////////////////////////////////////////////////
    // ComponentUI Interface Implementation methods
    /////////////////////////////////////////////////////////////////////////////
    public static ComponentUI createUI(JComponent b)    {
        return new BasicAxisUI((BasicAxis)b);
    }

    public void installUI(JComponent c)   {
        this.axis=(BasicAxis)c;
        this.axisStateMonitor=new ChangeHandler();
        //you decide what kind of ruler here. A ruler, acting as a strategy, provide paint algorithmn
        //ruler=new ColorRuler( axis.getOrient() ,axis.getActiveSize(), axis.getAxisLocation() ,axis.getTickRange() );

        this.updateRuler() ;//initial ruler
        //This basicUI won't install any listeners
        installListeners( axis);
    }
    protected void installListeners(BasicAxis axis){

        axis.getModel().addChangeListener(this.axisStateMonitor );
    }

    public void uninstallUI(JComponent c) {
        axis.setRuler(null);
        this.axis =null;

        //this.ruler =null;
    }


    public void paint( Graphics g, JComponent c )   {
        Ruler ruler=this.getRuler() ;
        if (ruler!=null) {
            //this.updateRuler() ;
            ruler.paintComponent(g);
        }
       if(axis.isShowFilterTick() )  {
        paintShowRangeTick(g);
       }

    }
    protected  void paintShowRangeTick(Graphics g){

        Range r=this.axis.getShowRange();
        Ruler ruler=this.getRuler() ;
        if(axis.getOrient()==Ruler.VERTICAL ){ //do not need to paint show range for XAxis
            int ymax=ruler.getGraphicValueOf(r.getMax() );
            int ymin=ruler.getGraphicValueOf(r.getMin() );

            int x=ruler.getLocation().x-6;

            g.setColor(Color.green );
            g.fillRect(x,ymax,5,5);
            g.fillRect(x,ymin,5,5);
        }
    }
    /*******************************************************************************************************
     *                operation
     *******************************************************************************************************/
    /*public float getGraphicValueOf(float realValue){
        return this.ruler.getGraphicValueOf(realValue);

    }*/
    public float getValueOf(int gv){
        Ruler ruler=this.getRuler() ;
        return ruler.getValueOf(gv);
    }
    /**
     *
     * @param deltaV   change of graphic value
     * @return         change of real value correpsonding to deltaV
     */
    public float getValueOfchange(float deltaV) {
        Ruler ruler=this.getRuler() ;
        return ruler.getValueOfchange(deltaV);
    }
    /*******************************************************************************************************
     *                Data model listener
     *******************************************************************************************************/
    /**
     * monitor the change on axis's state
     */
    public class ChangeHandler implements ChangeListener {
        //called whenever axis's model changed
        public void stateChanged(ChangeEvent e) {

	        updateRuler();
            axis.repaint();

        }
    }
     /**
     * Called whenever state is changed
     * subclass need reimplement the method based on ruler type
     *
     */
    protected  void updateRuler(){
         //todo, to improve performance, can only update specific property of ruler based property name 
        Ruler ruler=this.getRuler() ;
        ruler.setOrient(axis.getOrient() );
        ruler.setLength(this.axis.getActiveSize() );
        //this.ruler.setTickRange(this.axis.getDataRange() );
        ruler.setTickRange(this.axis.getTickRange() );

        ruler.setLocation(this.axis.getAxisLocation() );
        if (axis instanceof YAxis){
            CategoryList categoryList=((YAxis)this.axis).getCategoryList();
            /*if (axis.getName().equalsIgnoreCase("area")){

            }*/
            if(ruler instanceof ColorRuler){
                ColorRuler r=(edu.psu.geovista.app.plot.ruler.ColorRuler) ruler ;
                if (categoryList!=null)
                    r.setCategoryList(categoryList );
                else
                    r.setCategoryList(null);
            }
        }
    }

   
    /**
     * U can get the ruler instance and configure its properties, but u are responsible for update (repaint) axis
     * @return
     */
    public Ruler getRuler() {
        return this.axis.getRuler();
    }

}
